using System;
using System.Collections.Generic;
using System.Text;

namespace Developex.DatabaseWrapper.Fields
{
	/// <summary>
	/// Fictious field
	/// </summary>
	/// <typeparam name="T"></typeparam>
	public class FictitiousField<T> : Field<T>
	{
		#region Public Properties

		private string selectExpression = null;

		/// <summary>
		/// get/set custom select expression, {0} is table name
		/// </summary>
		/// <remarks>
		/// should be set, otherwise field will be not be used
		/// </remarks>
		public string SelectExpression
		{
			get { return selectExpression; }
			set { selectExpression = value; }
		}

		private string customJoinString;

		///<summary>
		///</summary>
		public string CustomJoinString
		{
			get { return customJoinString; }
			set { customJoinString = value; }
		}

		#endregion

		#region Overrides

		/// <summary>
		/// Expression used in SELECT query
		/// </summary>
		public override string GetSelectExpression()
		{
			if (string.IsNullOrEmpty(selectExpression))
				return string.Empty;
			return string.Format(selectExpression, Parent.JoinTableName);
		}

		///<summary>
		///</summary>
		///<returns></returns>
		/// <remarks>overrided in ForeignField to avoid adding not used joins</remarks>
		public override bool NeedToPrepare()
		{
			return !string.IsNullOrEmpty(GetJoinExpression());
		}

		/// <summary>
		/// Add joins and etc.
		/// </summary>
		/// <param name="qb">query builder</param>
		/// <remarks>don't forget to call qb.</remarks>
		public override void PrepareForSelectQuery(QueryBuilder qb)
		{
			string join = GetJoinExpression();
			if (string.IsNullOrEmpty(join))
				return;
			qb.Join.Add(join);
		}

		///<summary>
		/// Get join expression for this field
		///</summary>
		///<returns></returns>
		public virtual string GetJoinExpression()
		{
			return !string.IsNullOrEmpty(CustomJoinString) ? string.Format(CustomJoinString, Parent.JoinTableName) : null;
		}

		/// <summary>
		/// Clone
		/// </summary>
		/// <returns></returns>
		public override object Clone()
		{
			FictitiousField<T> field = (FictitiousField<T>)base.Clone();
			field.selectExpression = selectExpression;
			field.customJoinString = customJoinString;
			return field;
		}

		///<summary>
		/// Create object 
		///</summary>
		///<returns></returns>
		/// <remarks>
		/// Here should be only object creation, all data copy should be in overrided Clone function.
		/// Used only in base version of Clone function.
		/// Should be overrided for ICloneable interface.
		/// </remarks>
		protected override Field<T> CreateObjectForClone()
		{
			return new FictitiousField<T>(null);
		}

		#endregion

		#region Constructors

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="name"></param>
		public FictitiousField(string name)
			: base(name, FieldFlags.Fictitious)
		{
		}

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="name"></param>
		/// <param name="selectExpression">{0} is table name</param>
		public FictitiousField(string name, string selectExpression)
			: base(name, FieldFlags.Fictitious)
		{
			this.selectExpression = selectExpression;
		}

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="name"></param>
		/// <param name="flags"></param>
		public FictitiousField(string name, FieldFlags flags)
			: base(name, flags | FieldFlags.Fictitious)
		{
		}

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="name"></param>
		/// <param name="flags"></param>
		/// <param name="selectExpression">{0} is table name</param>
		public FictitiousField(string name, FieldFlags flags, string selectExpression)
			: base(name, flags | FieldFlags.Fictitious)
		{
			this.selectExpression = selectExpression;
		}

		#endregion
	}
}
